import { type Address, parseAbiParameters } from 'abitype'
import { assertType, describe, expect, test } from 'vitest'

import { seaportContractConfig } from '~test/src/abis.js'
import { address } from '~test/src/constants.js'
import { multicall3Abi } from '../../constants/abis.js'
import type { Hex } from '../../types/misc.js'
import { getAddress } from '../address/getAddress.js'
import { hexToBytes } from '../encoding/toBytes.js'
import { decodeAbiParameters } from './decodeAbiParameters.js'
import { encodeAbiParameters } from './encodeAbiParameters.js'
import { getAbiItem } from './getAbiItem.js'

describe('static', () => {
  test('blank', () => {
    const result = decodeAbiParameters([], '0x')
    assertType<readonly []>(result)
    expect(result).toEqual([])
  })

  test('uint', () => {
    const result = decodeAbiParameters(
      [{ type: 'uint' }],
      '0x0000000000000000000000000000000000000000000000000000000000010f2c',
    )
    assertType<readonly [bigint]>(result)
    expect(result).toEqual([69420n])
  })

  test('uint8', () => {
    const result = decodeAbiParameters(
      parseAbiParameters('uint8'),
      '0x0000000000000000000000000000000000000000000000000000000000000020',
    )
    assertType<readonly [number]>(result)
    expect(result).toEqual([32])
  })

  test('uint32', () => {
    const result = decodeAbiParameters(
      parseAbiParameters('uint32'),
      '0x0000000000000000000000000000000000000000000000000000000000010f2c',
    )
    assertType<readonly [number]>(result)
    expect(result).toEqual([69420])
  })

  describe('int', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('int'),
        '0x0000000000000000000000000000000000000000000000000000000000010f2c',
      )
      assertType<readonly [bigint]>(result)
      expect(result).toEqual([69420n])
    })

    test('negative (twos compliment)', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('int'),
        '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef0d4',
      )
      assertType<readonly [bigint]>(result)
      expect(result).toEqual([-69420n])
    })
  })

  describe('int8', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('int8'),
        '0x000000000000000000000000000000000000000000000000000000000000007f',
      )
      assertType<readonly [number]>(result)
      expect(result).toEqual([127])
    })

    test('negative (twos compliment)', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('int8'),
        '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80',
      )
      assertType<readonly [number]>(result)
      expect(result).toEqual([-128])
    })
  })

  describe('int32', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('int32'),
        '0x000000000000000000000000000000000000000000000000000000007fffffff',
      )
      assertType<readonly [number]>(result)
      expect(result).toEqual([2147483647])
    })

    test('negative (twos compliment)', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('int32'),
        '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000',
      )
      assertType<readonly [number]>(result)
      expect(result).toEqual([-2147483648])
    })
  })

  describe('address', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('address'),
        '0x00000000000000000000000014dc79964da2c08b23698b3d3cc7ca32193d9955',
      )
      assertType<readonly [Address]>(result)
      expect(
        decodeAbiParameters(
          parseAbiParameters('address'),
          '0x00000000000000000000000014dc79964da2c08b23698b3d3cc7ca32193d9955',
        ),
      ).toEqual(['0x14dC79964da2C08b23698B3D3cc7Ca32193d9955'])
    })
  })

  describe('bytes8', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('bytes8'),
        '0x0123456789abcdef000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [Hex]>(result)
      expect(result).toEqual(['0x0123456789abcdef'])
    })
  })

  describe('bytes16', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('bytes16'),
        '0x0123456789abcdef0123456789abcdef00000000000000000000000000000000',
      )
      assertType<readonly [Hex]>(result)
      expect(result).toEqual(['0x0123456789abcdef0123456789abcdef'])
    })
  })

  describe('uint[3]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[3]'),
        '0x0000000000000000000000000000000000000000000000000000000000010f2c000000000000000000000000000000000000000000000000000000000000a45500000000000000000000000000000000000000000000000000000000190f1b44',
      )
      assertType<readonly [readonly [bigint, bigint, bigint]]>(result)
      expect(result).toEqual([[69420n, 42069n, 420420420n]])
    })
  })

  describe('int[3]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('int[3]'),
        '0x0000000000000000000000000000000000000000000000000000000000010f2cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5bab00000000000000000000000000000000000000000000000000000000190f1b44',
      )
      assertType<readonly [readonly [bigint, bigint, bigint]]>(result)
      expect(result).toEqual([[69420n, -42069n, 420420420n]])
    })
  })

  describe('address[2]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('address[2]'),
        '0x000000000000000000000000c961145a54c96e3ae9baa048c4f4d6b04c13916b000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
      )
      assertType<readonly [readonly [Address, Address]]>(result)
      expect(result).toEqual([
        [
          '0xc961145a54C96E3aE9bAA048c4F4D6b04C13916b',
          '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
        ],
      ])
    })
  })

  describe('bool[2]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('bool[2]'),
        '0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [readonly [boolean, boolean]]>(result)
      expect(result).toEqual([[true, false]])
    })
  })

  describe('uint[3][2]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[3][2]'),
        '0x0000000000000000000000000000000000000000000000000000000000010f2c000000000000000000000000000000000000000000000000000000000000a45500000000000000000000000000000000000000000000000000000000190f1b4400000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000001a6',
      )
      assertType<
        readonly [
          readonly [
            readonly [bigint, bigint, bigint],
            readonly [bigint, bigint, bigint],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [
          [69420n, 42069n, 420420420n],
          [420n, 44n, 422n],
        ],
      ])
    })
  })

  describe('uint[3][2][4]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint[3][2][4]'),
        '0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000018',
      )
      assertType<
        readonly [
          readonly [
            readonly [
              readonly [bigint, bigint, bigint],
              readonly [bigint, bigint, bigint],
            ],
            readonly [
              readonly [bigint, bigint, bigint],
              readonly [bigint, bigint, bigint],
            ],
            readonly [
              readonly [bigint, bigint, bigint],
              readonly [bigint, bigint, bigint],
            ],
            readonly [
              readonly [bigint, bigint, bigint],
              readonly [bigint, bigint, bigint],
            ],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [
          [
            [1n, 2n, 3n],
            [4n, 5n, 6n],
          ],
          [
            [7n, 8n, 9n],
            [10n, 11n, 12n],
          ],
          [
            [13n, 14n, 15n],
            [16n, 17n, 18n],
          ],
          [
            [19n, 20n, 21n],
            [22n, 23n, 24n],
          ],
        ],
      ])
    })
  })

  describe('struct: (uint256,bool,address)', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('(uint256 x, bool y, address z)'),
        '0x00000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
      )
      assertType<
        readonly [
          {
            x: bigint
            y: boolean
            z: Hex
          },
        ]
      >(result)
      expect(result).toEqual([
        { x: 420n, y: true, z: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC' },
      ])
    })
  })

  describe('struct: (uint256,bool,address)', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('(uint256, bool, address)'),
        '0x00000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
      )
      assertType<readonly [readonly [bigint, boolean, Hex]]>(result)
      expect(result).toEqual([
        [420n, true, '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
      ])
    })
  })

  describe('struct: (uint256,bool,address)', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('(uint256 x, bool, address z)'),
        '0x00000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
      )
      assertType<readonly [readonly [bigint, boolean, Hex]]>(result)
      expect(result).toEqual([
        [420n, true, '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
      ])
    })
  })

  describe('struct: ()', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        [{ type: 'tuple', components: [] }],
        '0x00000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
      )
      assertType<readonly [readonly []]>(result)
      expect(result).toEqual([[]])
    })
  })

  describe('struct: ((uint256,bool,address),(uint256,bool,address),uint8[2])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters(
          '((uint256 x,bool y,address z) foo,(uint256 x,bool y,address z) baz,uint8[2] x)',
        ),
        '0x00000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac00000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c961145a54c96e3ae9baa048c4f4d6b04c13916b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002',
      )
      assertType<
        readonly [
          {
            foo: {
              x: bigint
              y: boolean
              z: Hex
            }
            baz: {
              x: bigint
              y: boolean
              z: Hex
            }
            x: readonly [number, number]
          },
        ]
      >(result)
      expect(result).toEqual([
        {
          foo: {
            x: 420n,
            y: true,
            z: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
          },
          baz: {
            x: 69n,
            y: false,
            z: '0xc961145a54C96E3aE9bAA048c4F4D6b04C13916b',
          },
          x: [1, 2],
        },
      ])
    })
  })

  describe('uint256[2],bool,string[3]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[2],bool,string[3]'),
        '0x00000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000057761676d6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047669656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036c6f6c0000000000000000000000000000000000000000000000000000000000',
      )
      assertType<
        readonly [
          readonly [bigint, bigint],
          boolean,
          readonly [string, string, string],
        ]
      >(result)
      expect(result).toEqual([[420n, 69n], true, ['wagmi', 'viem', 'lol']])
    })
  })

  describe('uint256[2],bool,string[3]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[2],bool,string[3]'),
        '0x00000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000057761676d6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047669656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036c6f6c0000000000000000000000000000000000000000000000000000000000',
      )
      assertType<
        readonly [
          readonly [bigint, bigint],
          boolean,
          readonly [string, string, string],
        ]
      >(result)
      expect(result).toEqual([[420n, 69n], true, ['wagmi', 'viem', 'lol']])
    })
  })

  describe('uint,bool,address', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint,bool,address'),
        '0x00000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c961145a54c96e3ae9baa048c4f4d6b04c13916b',
      )
      assertType<readonly [bigint, boolean, string]>(result)
      expect(result).toEqual([
        420n,
        true,
        '0xc961145a54C96E3aE9bAA048c4F4D6b04C13916b',
      ])
    })
  })
})

describe('dynamic', () => {
  describe('string', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('string'),
        '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [string]>(result)
      expect(result).toEqual(['wagmi'])
    })

    test('empty', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('string'),
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [string]>(result)
      expect(result).toEqual([''])
    })

    test('default', () => {
      expect(
        decodeAbiParameters(
          parseAbiParameters('string'),
          '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002da4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e204e756e63206661756369627573206c6f72656d2061206c696265726f20617563746f7220636f6e64696d656e74756d2e20446f6e6563206f726e617265206d617373612072686f6e637573206c616375732072757472756d2c20656765742070756c76696e6172206172637520656c656d656e74756d2e204e756e63206d6175726973206c6f72656d2c20736f64616c65732065676574207669766572726120696e2c20657569736d6f642071756973206d692e205072616573656e74206e656320636f6d6d6f646f206c656f2e2050686173656c6c757320636f6e64696d656e74756d206d61757269732073656420616363756d73616e20656c656966656e642e205072616573656e7420616320626c616e6469742073656d2c2065742072757472756d20697073756d2e20457469616d20696e2074656c6c757320616320656e696d20666163696c6973697320756c7472696365732e20467573636520616320766573746962756c756d207175616d2e204475697320736564207075727573207363656c657269737175652c20736f6c6c696369747564696e20657261742061632c2070756c76696e6172206e6973692e2050656c6c656e746573717565206575207075727573206e65632073617069656e207665686963756c6120636f6e76616c6c69732075742076656c20656c69742e2053757370656e6469737365206567657420657820766974616520656e696d20766f6c7574706174207363656c657269737175652e20536564207175697320656c6974207472697374697175652065726174206c756374757320656765737461732061206163206f64696f2e2044756973207665686963756c6120656e696d206163206d6574757320677261766964612c2076656c206d6178696d7573206e69736920696d706572646965742e000000000000',
        ),
      ).toMatchInlineSnapshot(
        `
        [
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc faucibus lorem a libero auctor condimentum. Donec ornare massa rhoncus lacus rutrum, eget pulvinar arcu elementum. Nunc mauris lorem, sodales eget viverra in, euismod quis mi. Praesent nec commodo leo. Phasellus condimentum mauris sed accumsan eleifend. Praesent ac blandit sem, et rutrum ipsum. Etiam in tellus ac enim facilisis ultrices. Fusce ac vestibulum quam. Duis sed purus scelerisque, sollicitudin erat ac, pulvinar nisi. Pellentesque eu purus nec sapien vehicula convallis ut vel elit. Suspendisse eget ex vitae enim volutpat scelerisque. Sed quis elit tristique erat luctus egestas a ac odio. Duis vehicula enim ac metus gravida, vel maximus nisi imperdiet.",
        ]
      `,
      )
    })

    test('emojis', () => {
      expect(
        decodeAbiParameters(
          parseAbiParameters('string'),
          '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026f09f91a8e2808df09f91a8e2808df09f91a6e2808df09f91a6f09f8fb4e2808de298a0efb88f0000000000000000000000000000000000000000000000000000',
        ),
      ).toMatchInlineSnapshot(
        `
        [
          "👨‍👨‍👦‍👦🏴‍☠️",
        ]
      `,
      )
    })
  })

  describe('string,uint,bool', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('string,uint,bool'),
        '0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [string, bigint, boolean]>(result)
      expect(result).toEqual(['wagmi', 420n, true])
    })
  })

  describe('uint[2],bool,string', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint[2],bool,string'),
        '0x00000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [readonly [bigint, bigint], boolean, string]>(result)
      expect(result).toEqual([[420n, 69n], true, 'wagmi'])
    })
  })

  describe('bytes', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('bytes'),
        '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030420690000000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [Hex]>(result)
      expect(result).toEqual(['0x042069'])
    })
  })

  describe('(uint256[][2])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][2]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001',
      )
      assertType<readonly [readonly [readonly bigint[], readonly bigint[]]]>(
        result,
      )
      expect(result).toEqual([
        [
          [1n, 2n, 3n, 4n],
          [3n, 2n, 1n],
        ],
      ])
    })
  })

  describe('uint256[2][][2]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[2][][2]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b',
      )
      assertType<
        readonly [
          readonly [
            readonly (readonly [bigint, bigint])[],
            readonly (readonly [bigint, bigint])[],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [
          [
            [1n, 2n],
            [4n, 5n],
          ],
          [
            [8n, 9n],
            [10n, 11n],
          ],
        ],
      ])
    })
  })

  describe('uint256[][][2]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][][2]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a',
      )
      assertType<
        readonly [
          readonly [
            readonly (readonly bigint[])[],
            readonly (readonly bigint[])[],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [
          [
            [1n, 2n, 3n],
            [4n, 5n, 6n, 7n],
          ],
          [[8n], [9n, 10n]],
        ],
      ])
    })
  })

  describe('uint256[][1][1]', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][1][1]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003',
      )
      assertType<readonly [readonly [readonly [readonly bigint[]]]]>(result)
      expect(result).toEqual([[[[1n, 2n, 3n]]]])
    })
  })

  describe('(uint256[][2][2])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][2][2]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a',
      )
      assertType<
        readonly [
          readonly [
            readonly [readonly bigint[], readonly bigint[]],
            readonly [readonly bigint[], readonly bigint[]],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [
          [
            [1n, 2n, 3n],
            [4n, 5n, 6n, 7n],
          ],
          [[8n], [9n, 10n]],
        ],
      ])
    })
  })

  describe('(uint256[][3][2])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][3][2]'),
        '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011',
      )
      assertType<
        readonly [
          readonly [
            readonly [readonly bigint[], readonly bigint[], readonly bigint[]],
            readonly [readonly bigint[], readonly bigint[], readonly bigint[]],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [
          [
            [1n, 2n, 3n],
            [4n, 5n, 6n, 7n],
            [8n, 9n, 10n],
          ],
          [[11n], [12n, 13n], [14n, 15n, 16n, 17n]],
        ],
      ])
    })
  })

  describe('(uint256[][2][3])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][2][3]'),
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011',
      )
      assertType<
        readonly [
          readonly [
            readonly [readonly bigint[], readonly bigint[]],
            readonly [readonly bigint[], readonly bigint[]],
            readonly [readonly bigint[], readonly bigint[]],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [
          [
            [1n, 2n],
            [3n, 4n, 5n],
          ],
          [
            [6n, 7n, 8n],
            [9n, 10n],
          ],
          [
            [11n, 12n, 13n],
            [14n, 15n, 16n, 17n],
          ],
        ],
      ])
    })
  })

  describe('(uint256[][2][3][4])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][2][3][4]'),
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006',
      )
      assertType<
        readonly [
          readonly [
            readonly [
              readonly [readonly bigint[], readonly bigint[]],
              readonly [readonly bigint[], readonly bigint[]],
              readonly [readonly bigint[], readonly bigint[]],
            ],
            readonly [
              readonly [readonly bigint[], readonly bigint[]],
              readonly [readonly bigint[], readonly bigint[]],
              readonly [readonly bigint[], readonly bigint[]],
            ],
            readonly [
              readonly [readonly bigint[], readonly bigint[]],
              readonly [readonly bigint[], readonly bigint[]],
              readonly [readonly bigint[], readonly bigint[]],
            ],
            readonly [
              readonly [readonly bigint[], readonly bigint[]],
              readonly [readonly bigint[], readonly bigint[]],
              readonly [readonly bigint[], readonly bigint[]],
            ],
          ],
        ]
      >(result)
      expect(result).toMatchInlineSnapshot(`
        [
          [
            [
              [
                [
                  1n,
                  2n,
                  3n,
                ],
                [
                  4n,
                  5n,
                  6n,
                  7n,
                ],
              ],
              [
                [
                  8n,
                ],
                [
                  9n,
                  10n,
                ],
              ],
              [
                [
                  11n,
                  12n,
                ],
                [
                  13n,
                ],
              ],
            ],
            [
              [
                [
                  14n,
                  15n,
                ],
                [
                  16n,
                  17n,
                  18n,
                ],
              ],
              [
                [
                  0n,
                  1n,
                ],
                [
                  2n,
                  3n,
                  4n,
                ],
              ],
              [
                [
                  5n,
                  6n,
                ],
                [
                  1n,
                  2n,
                  1n,
                ],
              ],
            ],
            [
              [
                [
                  1n,
                  2n,
                  1n,
                  2n,
                ],
                [
                  1n,
                  5n,
                  6n,
                ],
              ],
              [
                [
                  1n,
                ],
                [
                  2n,
                ],
              ],
              [
                [
                  1n,
                  2n,
                  3n,
                ],
                [
                  5n,
                  6n,
                  7n,
                ],
              ],
            ],
            [
              [
                [
                  9n,
                  8n,
                  7n,
                ],
                [
                  5n,
                  5n,
                  5n,
                ],
              ],
              [
                [
                  1n,
                  2n,
                  3n,
                ],
                [
                  4n,
                  4n,
                  4n,
                ],
              ],
              [
                [
                  5n,
                  5n,
                  5n,
                ],
                [
                  6n,
                  6n,
                  6n,
                ],
              ],
            ],
          ],
        ]
      `)
    })
  })

  describe('(uint256[2][][2])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[2][][2]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a',
      )
      assertType<
        readonly [
          readonly [
            readonly (readonly [bigint, bigint])[],
            readonly (readonly [bigint, bigint])[],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [
          [
            [1n, 2n],
            [4n, 5n],
          ],
          [
            [8n, 9n],
            [10n, 11n],
            [9n, 10n],
          ],
        ],
      ])
    })
  })

  describe('(uint[])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000037',
      )
      assertType<readonly [readonly bigint[]]>(result)
      expect(result).toEqual([[420n, 69n, 22n, 55n]])
    })

    test('empty', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[]'),
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [readonly bigint[]]>(result)
      expect(result).toEqual([[]])
    })
  })

  describe('(uint[][])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][]'),
        '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000045',
      )
      assertType<readonly [readonly (readonly bigint[])[]]>(result)
      expect(result).toEqual([[[420n, 69n]]])
    })

    test('empty', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [readonly (readonly bigint[])[]]>(result)
      expect(result).toEqual([[[]]])
    })

    // cast abi-encode "a(uint[][])" "[[420,69],[22,55,22],[51,52,66,11]]"
    test('complex', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('uint256[][]'),
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000000b',
      )
      assertType<readonly [readonly (readonly bigint[])[]]>(result)
      expect(result).toEqual([
        [
          [420n, 69n],
          [22n, 55n, 22n],
          [51n, 52n, 66n, 11n],
        ],
      ])
    })
  })

  describe('(string[2])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('string[2]'),
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000057761676d6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047669656d00000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [readonly [string, string]]>(result)
      expect(result).toEqual([['wagmi', 'viem']])
    })
  })

  describe('(string[2][3])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('string[2][3]'),
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000057761676d6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047669656d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000046a616b65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003746f6d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036c6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046861686100000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [readonly (readonly [string, string])[]]>(result)
      expect(result).toEqual([
        [
          ['wagmi', 'viem'],
          ['jake', 'tom'],
          ['lol', 'haha'],
        ],
      ])
    })
  })

  describe('(bytes[2])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('bytes[2]'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000002123400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044141414100000000000000000000000000000000000000000000000000000000',
      )
      assertType<readonly [readonly [Hex, Hex]]>(result)
      expect(result).toEqual([['0x1234', '0x41414141']])
    })
  })

  describe('(uint256, string)', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('(uint256, string)'),
        '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000',
      )
      expect(result).toEqual([[23n, 'hello']])
    })
  })

  describe('((uint256, string))', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('((uint256, string))'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000',
      )
      expect(result).toEqual([[[23n, 'hello']]])
    })
  })

  describe('((uint256[], string))', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('((uint256[], string))'),
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000',
      )
      expect(result).toEqual([[[[23n, 46n], 'hello']]])
    })
  })

  // cast abi-encode "a((uint256[],bool,string[]))" "([1,2,3,4],true,[hello,world])"
  describe('(uint256[],bool,string[])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('(uint256[] x,bool y,string[] z)'),
        '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005776f726c64000000000000000000000000000000000000000000000000000000',
      )
      assertType<
        readonly [
          {
            x: readonly bigint[]
            y: boolean
            z: readonly string[]
          },
        ]
      >(result)
      expect(result).toEqual([
        {
          x: [1n, 2n, 3n, 4n],
          y: true,
          z: ['hello', 'world'],
        },
      ])
    })
  })

  describe('((uint256[] x,bool y,string[] z) foo,uint256 a,string[] b)', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters(
          '((uint256[] x,bool y,string[] z) foo,uint256 a,string[] b)',
        ),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005776f726c6400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000057761676d6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047669656d00000000000000000000000000000000000000000000000000000000',
      )
      assertType<
        readonly [
          {
            foo: {
              x: readonly bigint[]
              y: boolean
              z: readonly string[]
            }
            a: bigint
            b: readonly string[]
          },
        ]
      >(result)
      expect(result).toEqual([
        {
          foo: {
            x: [1n, 2n, 3n, 4n],
            y: true,
            z: ['hello', 'world'],
          },
          a: 420n,
          b: ['wagmi', 'viem'],
        },
      ])
    })
  })

  describe('((uint256[],bool,string[]) foo,uint256,string[])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters('((uint256[],bool,string[]) foo,uint256,string[])'),
        '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005776f726c6400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000057761676d6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047669656d00000000000000000000000000000000000000000000000000000000',
      )
      assertType<
        readonly [
          readonly [
            readonly [readonly bigint[], boolean, readonly string[]],
            bigint,
            readonly string[],
          ],
        ]
      >(result)
      expect(result).toEqual([
        [[[1n, 2n, 3n, 4n], true, ['hello', 'world']], 420n, ['wagmi', 'viem']],
      ])
    })
  })

  describe('(uint256[],bool,string[]),(((uint256[],bool,string[]),uint256,string[]),((uint256[],bool,string[]), uint256, string[]),uint256,string[])', () => {
    test('default', () => {
      const result = decodeAbiParameters(
        parseAbiParameters(
          '(uint256[] x, bool y, string[] z) bazIn, (((uint256[] x, bool y, string[] z) foo, uint256 a, string[] b) foo, ((uint256[] x, bool y, string[] z) foo, uint256 a, string[] b) bar, uint256 c, string[] d) gmiIn',
        ),
        '0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005776f726c640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000004026aa0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000046e696365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004686168610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000057761676d690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006616c6c646179000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000010f2c00000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000004746869730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026973000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005706172616d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005746865726500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036c6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046861686100000000000000000000000000000000000000000000000000000000',
      )
      assertType<
        readonly [
          {
            x: readonly bigint[]
            y: boolean
            z: readonly string[]
          },
          {
            foo: {
              foo: {
                x: readonly bigint[]
                y: boolean
                z: readonly string[]
              }
              a: bigint
              b: readonly string[]
            }
            bar: {
              foo: {
                x: readonly bigint[]
                y: boolean
                z: readonly string[]
              }
              a: bigint
              b: readonly string[]
            }
            c: bigint
            d: readonly string[]
          },
        ]
      >(result)
      expect(result).toEqual([
        {
          x: [1n, 2n, 3n, 4n],
          y: true,
          z: ['hello', 'world'],
        },
        {
          foo: {
            a: 420n,
            b: ['wagmi', 'allday'],
            foo: {
              x: [420n, 69n],
              y: true,
              z: ['nice', 'haha'],
            },
          },
          bar: {
            a: 69420n,
            b: ['hello', 'there'],
            foo: {
              x: [420n, 420n],
              y: true,
              z: ['this', 'is', 'a', 'param'],
            },
          },
          c: 4204202n,
          d: ['lol', 'haha'],
        },
      ])
    })
  })
})

describe('seaport', () => {
  test('cancel', () => {
    const cancel = getAbiItem({
      abi: seaportContractConfig.abi,
      name: 'cancel',
    })
    const data = decodeAbiParameters(
      cancel.inputs,
      '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000540000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000001caab5c3b30000000000000000000000000000000000000000000000000000001caab5c3b3511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a00000000000000000000000000000000000000000000000000000000498f3973511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a00000000000000000000000000000000000000000000000000000000498f39730000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000005414d89a8bf7e99d732bc52f3e6a3ef461c0c07800000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000034fb5b7000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000001e0f30000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000001caab5c3b30000000000000000000000000000000000000000000000000000001caab5c3b3511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a00000000000000000000000000000000000000000000000000000000498f3973511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a00000000000000000000000000000000000000000000000000000000498f39730000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000005414d89a8bf7e99d732bc52f3e6a3ef461c0c07800000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000034fb5b7000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000001e0f30000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045',
    )
    expect(data).toEqual([
      [
        {
          conduitKey:
            '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
          consideration: [
            {
              endAmount: 420n,
              identifierOrCriteria: 69n,
              itemType: 10,
              recipient: getAddress(address.vitalik),
              startAmount: 6n,
              token: getAddress(address.burn),
            },
            {
              endAmount: 141n,
              identifierOrCriteria: 55n,
              itemType: 16,
              recipient: getAddress(address.vitalik),
              startAmount: 15n,
              token: getAddress(address.burn),
            },
          ],
          counter: 1234123123n,
          endTime: 123123123123n,
          offer: [
            {
              endAmount: 420n,
              identifierOrCriteria: 69n,
              itemType: 10,
              startAmount: 6n,
              token: getAddress(address.burn),
            },
            {
              endAmount: 11n,
              identifierOrCriteria: 515n,
              itemType: 10,
              startAmount: 6n,
              token: getAddress(address.usdcHolder),
            },
            {
              endAmount: 123123n,
              identifierOrCriteria: 55555511n,
              itemType: 10,
              startAmount: 111n,
              token: getAddress(address.vitalik),
            },
          ],
          offerer: getAddress(address.vitalik),
          orderType: 10,
          salt: 1234123123n,
          startTime: 123123123123n,
          zone: getAddress(address.vitalik),
          zoneHash:
            '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
        },
        {
          conduitKey:
            '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
          consideration: [
            {
              endAmount: 420n,
              identifierOrCriteria: 69n,
              itemType: 10,
              recipient: getAddress(address.vitalik),
              startAmount: 6n,
              token: getAddress(address.burn),
            },
            {
              endAmount: 141n,
              identifierOrCriteria: 55n,
              itemType: 16,
              recipient: getAddress(address.vitalik),
              startAmount: 15n,
              token: getAddress(address.burn),
            },
          ],
          counter: 1234123123n,
          endTime: 123123123123n,
          offer: [
            {
              endAmount: 420n,
              identifierOrCriteria: 69n,
              itemType: 10,
              startAmount: 6n,
              token: getAddress(address.burn),
            },
            {
              endAmount: 11n,
              identifierOrCriteria: 515n,
              itemType: 10,
              startAmount: 6n,
              token: getAddress(address.usdcHolder),
            },
            {
              endAmount: 123123n,
              identifierOrCriteria: 55555511n,
              itemType: 10,
              startAmount: 111n,
              token: getAddress(address.vitalik),
            },
          ],
          offerer: getAddress(address.vitalik),
          orderType: 10,
          salt: 1234123123n,
          startTime: 123123123123n,
          zone: getAddress(address.vitalik),
          zoneHash:
            '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
        },
      ],
    ])
  })

  test('fulfillAdvancedOrder', () => {
    const fulfillAdvancedOrder = getAbiItem({
      abi: seaportContractConfig.abi,
      name: 'fulfillAdvancedOrder',
    })
    const data = decodeAbiParameters(
      fulfillAdvancedOrder.inputs,
      '0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006a0511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000001caab5c3b30000000000000000000000000000000000000000000000000000001caab5c3b3511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a00000000000000000000000000000000000000000000000000000000498f3973511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a0000000000000000000000000000000000000000000000000000000000010f2c0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000005414d89a8bf7e99d732bc52f3e6a3ef461c0c07800000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000034fb5b7000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000001e0f30000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000000312312300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003123123000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004cf000000000000000000000000000000000000000000000000000000000000109200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
    )
    expect(data).toEqual([
      {
        denominator: 69n,
        extraData: '0x123123',
        numerator: 420n,
        parameters: {
          conduitKey:
            '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
          consideration: [
            {
              endAmount: 420n,
              identifierOrCriteria: 69n,
              itemType: 10,
              recipient: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
              startAmount: 6n,
              token: '0x0000000000000000000000000000000000000000',
            },
            {
              endAmount: 141n,
              identifierOrCriteria: 55n,
              itemType: 16,
              recipient: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
              startAmount: 15n,
              token: '0x0000000000000000000000000000000000000000',
            },
          ],
          endTime: 123123123123n,
          offer: [
            {
              endAmount: 420n,
              identifierOrCriteria: 69n,
              itemType: 10,
              startAmount: 6n,
              token: '0x0000000000000000000000000000000000000000',
            },
            {
              endAmount: 11n,
              identifierOrCriteria: 515n,
              itemType: 10,
              startAmount: 6n,
              token: '0x5414d89a8bF7E99d732BC52f3e6A3Ef461c0C078',
            },
            {
              endAmount: 123123n,
              identifierOrCriteria: 55555511n,
              itemType: 10,
              startAmount: 111n,
              token: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
            },
          ],
          offerer: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
          orderType: 10,
          salt: 1234123123n,
          startTime: 123123123123n,
          totalOriginalConsiderationItems: 69420n,
          zone: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
          zoneHash:
            '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
        },
        signature: '0x123123',
      },
      [
        {
          criteriaProof: [
            '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
          ],
          identifier: 4242n,
          index: 1231n,
          orderIndex: 11n,
          side: 1,
        },
      ],
      '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
      '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
    ])
  })
})

describe('multicall3', () => {
  test('zero data', () => {
    expect(
      decodeAbiParameters(
        multicall3Abi[0].outputs,
        '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000',
      ),
    ).toMatchInlineSnapshot(`
      [
        [
          {
            "returnData": "0x",
            "success": true,
          },
        ],
      ]
    `)
  })

  test('zero data + non-zero data', () => {
    expect(
      decodeAbiParameters(
        multicall3Abi[0].outputs,
        '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000d752bd588f61926e40000000000000000000000000000000000000000000000002e0e220d3d6cf5630000000000000000000000000000000000000000000000000000000063fa0b5f',
      ),
    ).toMatchInlineSnapshot(`
      [
        [
          {
            "returnData": "0x",
            "success": true,
          },
          {
            "returnData": "0x00000000000000000000000000000000000000000000000d752bd588f61926e40000000000000000000000000000000000000000000000002e0e220d3d6cf5630000000000000000000000000000000000000000000000000000000063fa0b5f",
            "success": true,
          },
        ],
      ]
    `)
  })
})

test('bytes input', () => {
  const result = decodeAbiParameters(
    parseAbiParameters(
      '(uint256[] x, bool y, string[] z) bazIn, (((uint256[] x, bool y, string[] z) foo, uint256 a, string[] b) foo, ((uint256[] x, bool y, string[] z) foo, uint256 a, string[] b) bar, uint256 c, string[] d) gmiIn',
    ),
    hexToBytes(
      '0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005776f726c640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000004026aa0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000046e696365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004686168610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000057761676d690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006616c6c646179000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000010f2c00000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000004746869730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026973000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005706172616d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005746865726500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036c6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046861686100000000000000000000000000000000000000000000000000000000',
    ),
  )
  expect(result).toEqual([
    {
      x: [1n, 2n, 3n, 4n],
      y: true,
      z: ['hello', 'world'],
    },
    {
      foo: {
        a: 420n,
        b: ['wagmi', 'allday'],
        foo: {
          x: [420n, 69n],
          y: true,
          z: ['nice', 'haha'],
        },
      },
      bar: {
        a: 69420n,
        b: ['hello', 'there'],
        foo: {
          x: [420n, 420n],
          y: true,
          z: ['this', 'is', 'a', 'param'],
        },
      },
      c: 4204202n,
      d: ['lol', 'haha'],
    },
  ])
})

test('data suffix', () => {
  expect(
    decodeAbiParameters(
      [
        {
          name: 'xIn',
          type: 'uint256',
        },
      ],
      '0x0000000000000000000000000000000000000000000000000000000000010f2cdeadbeef',
    ),
  ).toEqual([69420n])
})

test('data size too small', () => {
  expect(() =>
    decodeAbiParameters(
      [{ type: 'uint256' }],
      '0x0000000000000000000000000000000000000000000000000000000000010f',
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [AbiDecodingDataSizeTooSmallError: Data size of 31 bytes is too small for given parameters.

    Params: (uint256)
    Data:   0x0000000000000000000000000000000000000000000000000000000000010f (31 bytes)

    Version: viem@x.y.z]
  `)

  expect(() =>
    decodeAbiParameters(
      [{ type: 'uint256' }],
      hexToBytes(
        '0x0000000000000000000000000000000000000000000000000000000000010f',
      ),
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [AbiDecodingDataSizeTooSmallError: Data size of 31 bytes is too small for given parameters.

    Params: (uint256)
    Data:   0x0000000000000000000000000000000000000000000000000000000000010f (31 bytes)

    Version: viem@x.y.z]
  `)

  expect(() =>
    decodeAbiParameters(
      [{ type: 'uint256' }, { type: 'uint256' }],
      '0x0000000000000000000000000000000000000000000000000000000000010f2c',
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`32\` is out of bounds (\`0 < position < 32\`).

    Version: viem@x.y.z]
  `)
})

test('invalid type', () => {
  expect(() =>
    decodeAbiParameters(
      [{ name: 'x', type: 'lol' }],
      '0x0000000000000000000000000000000000000000000000000000000000000000',
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [InvalidAbiDecodingType: Type "lol" is not a valid decoding type.
    Please provide a valid ABI type.

    Docs: https://viem.sh/docs/contract/decodeAbiParameters
    Version: viem@x.y.z]
  `)
})

test('error: zero data', () => {
  expect(() =>
    decodeAbiParameters(
      [
        {
          inputs: [],
          name: 'foo',
          outputs: [
            {
              name: 'x',
              type: 'uint256',
            },
          ],
          stateMutability: 'pure',
          type: 'function',
        },
      ],
      '0x',
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [AbiDecodingZeroDataError: Cannot decode zero data ("0x") with ABI parameters.

    Version: viem@x.y.z]
  `)
})

test('error: recursive decode array', () => {
  const payload = `0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a${'0000000000000000000000000000000000000000000000000000000000000020'.repeat(
    64,
  )}`
  expect(() =>
    decodeAbiParameters(
      [{ type: 'uint256[][][][][][][][][][]' }],
      `0x${payload}`,
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [RecursiveReadLimitExceededError: Recursive read limit of \`8192\` exceeded (recursive read count: \`8193\`).

    Version: viem@x.y.z]
  `)
})

test('zst', () => {
  const payload =
    '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF' as const

  expect(() =>
    decodeAbiParameters([{ type: 'uint256[0][4294967295]' }], payload),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`64\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters([{ type: 'uint32[0][4294967295]' }], payload),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`64\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters([{ type: 'uint256[4294967295][4294967295]' }], payload),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`95\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters([{ type: 'uint32[4294967295][4294967295]' }], payload),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`95\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters([{ type: 'uint256[0][]' }], payload),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`64\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters([{ type: 'uint256[0][]' }], payload),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`64\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters([{ type: 'tuple[]', components: [] }], payload),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`64\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters(
      [{ type: 'tuple[]', components: [{ type: 'tuple', components: [] }] }],
      payload,
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`64\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters(
      [{ type: 'tuple[]', components: [{ type: 'uint32[0]' }] }],
      payload,
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`64\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters(
      [
        {
          type: 'tuple[]',
          components: [{ type: 'tuple', components: [{ type: 'uint32[0]' }] }],
        },
      ],
      payload,
    ),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`64\` is out of bounds (\`0 < position < 64\`).

    Version: viem@x.y.z]
  `)
})

test('recursive', () => {
  const arr2 = parseAbiParameters('uint256[][]')
  const arr4 = parseAbiParameters('uint256[][][][]')
  const arr10 = parseAbiParameters('uint256[][][][][][][][][][]')
  const a = [[[], [], [], [], [], [], [], [], [], []]] as const
  const p = encodeAbiParameters(arr2, a)
  expect(p).toEqual(
    '0x0000000000000000000000000000000000000000000000000000000000000020' + // ptr
      '000000000000000000000000000000000000000000000000000000000000000a' + // len=10
      '0000000000000000000000000000000000000000000000000000000000000140' +
      '0000000000000000000000000000000000000000000000000000000000000160' +
      '0000000000000000000000000000000000000000000000000000000000000180' +
      '00000000000000000000000000000000000000000000000000000000000001a0' +
      '00000000000000000000000000000000000000000000000000000000000001c0' +
      '00000000000000000000000000000000000000000000000000000000000001e0' +
      '0000000000000000000000000000000000000000000000000000000000000200' +
      '0000000000000000000000000000000000000000000000000000000000000220' +
      '0000000000000000000000000000000000000000000000000000000000000240' +
      '0000000000000000000000000000000000000000000000000000000000000260' + // ptrs end (10)
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000' +
      '0000000000000000000000000000000000000000000000000000000000000000', // 10 values
  )

  const payload =
    `0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a${'0000000000000000000000000000000000000000000000000000000000000020'.repeat(
      64,
    )}` as const
  expect(() =>
    decodeAbiParameters(arr10, payload),
  ).toThrowErrorMatchingInlineSnapshot(`
    [RecursiveReadLimitExceededError: Recursive read limit of \`8192\` exceeded (recursive read count: \`8193\`).

    Version: viem@x.y.z]
  `)

  const ptrArr = parseAbiParameters('uint256[]')
  // Try to break check
  const p2 = encodeAbiParameters(ptrArr, [
    Array.from({ length: 10 * 1024 }, (_, j) => BigInt(j + 1) * 32n),
  ])
  expect(() =>
    decodeAbiParameters(arr10, p2),
  ).toThrowErrorMatchingInlineSnapshot(`
    [PositionOutOfBoundsError: Position \`327744\` is out of bounds (\`0 < position < 327744\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters(arr4, p2),
  ).toThrowErrorMatchingInlineSnapshot(`
    [RecursiveReadLimitExceededError: Recursive read limit of \`8192\` exceeded (recursive read count: \`8193\`).

    Version: viem@x.y.z]
  `)
  expect(() =>
    decodeAbiParameters(arr2, p2),
  ).toThrowErrorMatchingInlineSnapshot(`
    [RecursiveReadLimitExceededError: Recursive read limit of \`8192\` exceeded (recursive read count: \`8193\`).

    Version: viem@x.y.z]
  `)
})

test('recursive 2', () => {
  const arr10 = parseAbiParameters('uint256[][][][][][][][][][]')
  const a = [[], [], [], [], [], [], [], [], [], []] as const
  const ptrArr = parseAbiParameters('uint256[]')
  const mainPtr = encodeAbiParameters(ptrArr, [
    a.map((i: any) => BigInt(a.length - i + 1) * 32n),
  ])
  expect(() =>
    decodeAbiParameters(arr10, `0x${mainPtr.slice(2).repeat(10 + 1)}`),
  ).toThrowErrorMatchingInlineSnapshot(`
    [RecursiveReadLimitExceededError: Recursive read limit of \`8192\` exceeded (recursive read count: \`8193\`).

    Version: viem@x.y.z]
  `)
})
